package com.trw.trp.action;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;

import com.trw.trp.bean.ModelBean;
import com.trw.trp.bean.ModelDetail;
import com.trw.trp.bean.OrderBean;
import com.trw.trp.bean.OrderScheduleInfo;
import com.trw.trp.bean.SearchCriteriaBean;
import com.trw.trp.bean.UserBean;
import com.trw.trp.dao.DaoFactory;
import com.trw.trp.dao.ModelDao;
import com.trw.trp.dao.OrderDao;
import com.trw.trp.msg.ResultMessage;
import com.trw.trp.util.ModelUtil;
import com.trw.trp.util.TRPConstants;
import com.trw.trp.util.TRPUtil;
import com.utuan.log.Log;
import com.utuan.log.LogFactory;
import com.utuan.util.TuanUtil;

public class OrderAction2 extends AbstractAction {

	private static Log log = LogFactory.getLog(OrderAction2.class);
	private static DateFormat DATE_FORMAT = new SimpleDateFormat("d/M/yyyy");
	private String start;
	private String limit;
	
	public String getStart() {
		return start;
	}

	public void setStart(String start) {
		this.start = start;
	}

	public String getLimit() {
		return limit;
	}

	public void setLimit(String limit) {
		this.limit = limit;
	}

	public String execute() {
		String back = getParamFromRequest("back");
		if (!"back".equals(back)) {
			TRPUtil.removeFromSession("selectedOrderId");
			TRPUtil.removeFromSession("selectedModelId");
		}
		return SUCCESS;
	}

	public void getPipeline() throws IOException {
		OrderDao dao = DaoFactory.getOrderDao();
		SearchCriteriaBean criteria = new SearchCriteriaBean();
		criteria.setDetail(true);
		List<OrderBean> orderList = dao.getOrders(criteria);
		long modelId = -1;
		try {
			String modelIdStr = getParamFromRequest("modelId");
			modelId = Long.parseLong(modelIdStr);
		} catch (Exception e) {
			log.warn(e);
		}
		int status = -999;
		try {
			status = Integer.parseInt(getParamFromRequest("status"));
		} catch (Exception e) {
			log.warn(e);
		}
		String addCriteria = getParamFromRequest("addCriteria");
		String addValue = getParamFromRequest("addValue");
		List<Map<String, String>> pipelineInfo = convertJsonData(orderList,
				false, modelId, status, addCriteria, addValue);
		int start = 0;
		int limit = 20;
		try {
			start = Integer.parseInt(this.start);
		} catch (Exception e) {
		}
		try {
			limit = Integer.parseInt(this.limit);
		} catch (Exception e) {
		}
		writeJSON(pipelineInfo, start, limit);
	}

	public void getPendingSchedule() throws IOException {
		OrderDao dao = DaoFactory.getOrderDao();
		SearchCriteriaBean criteria = new SearchCriteriaBean();
		criteria.setDetail(true);
		criteria.setMaxStatus(10);
		criteria.setMinStatus(3);
		List<OrderBean> orderList = dao.getOrders(criteria);
		String addCriteria = getParamFromRequest("addCriteria");
		String addValue = getParamFromRequest("addValue");
		// only green status schedule info record can be scheduled
		List<Map<String, String>> pendingSchedule = convertJsonData(orderList,
				true, -1, 4, addCriteria, addValue);
		writeJSON(pendingSchedule);
	}

	private List<Map<String, String>> convertJsonData(
			List<OrderBean> orderList, boolean onlyPending, long modelId,
			int status, String addCriteria, String addValue) {
		List<Map<String, String>> json = null;
		if (orderList != null && !orderList.isEmpty()) {
			json = new ArrayList<Map<String, String>>();
			Map<String, String> record = null;
			ModelBean model = null;
			ModelDetail detail = null;
			boolean inSchedule;
			for (OrderBean order : orderList) {
				if (order.getModelMap() == null
						|| order.getModelMap().size() == 0
						|| order.getModelMap().get(1) == null) {
					continue;
				}
				boolean orderStatusFlag = true;
				if (status > -999) {
					if (status < 100) {
						if (order.getStatus() != status) {
							orderStatusFlag = false;
						}
						if ((order.getStatus() == 1 || order.getStatus() == 2)
								&& (status == 1 || status == 2)) {
							orderStatusFlag = true;
						}
					} else {
						if (order.getStatus() < 100
								|| status != 100 + order.getInputStatus()) {
							orderStatusFlag = false;
						}
						if ((order.getStatus() == 101 || order.getStatus() == 102)
								&& (status == 101 || status == 102)) {
							orderStatusFlag = true;
						}
					}
				}
				order.generateOrderStatusName();
				Map<String, OrderScheduleInfo> scheduleInfoMap = order
						.getScheduleInfoMap();
				List<ModelBean> modelList = order.getModelMap().get(1);
				List<ModelDetail> detailList = order.getDetailMap().get(1);
				List<Long> modelIdList = new ArrayList<Long>();
				modelIdList.add(modelId);
				ModelDao mDao = DaoFactory.getModelDao();
				ModelBean modelBean = mDao.getModelById(modelId);
				if (modelBean != null && modelBean.getSubModelList() != null) {
					for (ModelBean subModel : modelBean.getSubModelList()) {
						modelIdList.add(subModel.getModelId());
					}
				}
				boolean orgOrderStatusFlag = orderStatusFlag;
				for (int i = 0; i < modelList.size(); i++) {
					orderStatusFlag = orgOrderStatusFlag;
					inSchedule = false;
					model = modelList.get(i);
					detail = detailList.get(i);
					if (modelId == -1
							|| modelIdList.contains(model.getModelId())) {
						record = new HashMap<String, String>();
						record.put("orderId", String
								.valueOf(order.getOrderId()));
						record.put("requestNo", order.getOrderNumber());
						record.put("testPurpose",
								order.getGeneralInfo() == null ? "" : order
										.getGeneralInfo().getTestPurpose());
						record.put("projectNumber",
								order.getGeneralInfo() == null ? "" : order
										.getGeneralInfo().getProjectNumber());
						record.put("project",
								order.getGeneralInfo() == null ? "" : order
										.getGeneralInfo().getProject());
						record.put("product",
								order.getGeneralInfo() == null ? "" : order
										.getGeneralInfo().getProduct());
						record.put("customer",
								order.getGeneralInfo() == null ? "" : order
										.getGeneralInfo().getCustomer());
						record
								.put(
										"teUser",
										(order.getGeneralInfo() == null || order
												.getGeneralInfo().getTestUser() == null) ? ""
												: order.getGeneralInfo()
														.getTestUser()
														.getName());
						record.put("modelName", model.getModelName());
						record.put("clientUniqueId", model.getClientUniqueId());
						record.put("plant", order.getGeneralInfo() == null ? ""
								: order.getGeneralInfo().getPlant());
						record.put("payer", order.getGeneralInfo() == null ? ""
								: order.getGeneralInfo().getPayer());

						record.put("status", order.getStatusName());

						// filter records here
						if (!TuanUtil.isEmptyString(addCriteria)
								&& !TuanUtil.isEmptyString(addValue)) {
							boolean exclude = false;
							if ("trpNo".equals(addCriteria)) {
								exclude = (record.get("requestNo")
										.toLowerCase().indexOf(
												addValue.toLowerCase()) == -1);
							} else if ("prjNum".equals(addCriteria)) {
								exclude = (record.get("projectNumber")
										.toLowerCase().indexOf(
												addValue.toLowerCase()) == -1);
							} else if ("prj".equals(addCriteria)) {
								exclude = (record.get("project").toLowerCase()
										.indexOf(addValue.toLowerCase()) == -1);
							} else if ("prd".equals(addCriteria)) {
								exclude = (record.get("product").toLowerCase()
										.indexOf(addValue.toLowerCase()) == -1);
							}
							if (exclude) {
								continue;
							}
						}

						Map<Long, ModelDetail.Field> fields = ModelUtil
								.getAllFields(detail);
						ModelDetail.Field field;
						if (model.getModelId() == 12) {
							field = fields.get(68L);
							record.put("testContent", field.getSelectedValue());
							field = fields.get(75L);
							record.put("hthm", field.getSelectedValue());
							field = fields.get(91L);
							record.put("htnm", field.getSelectedValue());
							field = fields.get(107L);
							record.put("htlm", field.getSelectedValue());
							field = fields.get(76L);
							record.put("rthm", field.getSelectedValue());
							field = fields.get(92L);
							record.put("rtnm", field.getSelectedValue());
							field = fields.get(108L);
							record.put("rtlm", field.getSelectedValue());
							field = fields.get(77L);
							record.put("lthm", field.getSelectedValue());
							field = fields.get(93L);
							record.put("ltnm", field.getSelectedValue());
							field = fields.get(109L);
							record.put("ltlm", field.getSelectedValue());
							StringBuilder sb = new StringBuilder();
							field = fields.get(39L);
							sb.append(field.getSelectedValue() == null ? ""
									: field.getSelectedValue());
							field = fields.get(41L);
							sb.append("(").append(
									field.getSelectedValue() == null ? ""
											: field.getSelectedValue());
							field = fields.get(40L);
							sb.append(" ~ ").append(
									field.getSelectedValue() == null ? ""
											: field.getSelectedValue()).append(
									")");
							record.put("ignitionTime", sb.toString());
							sb = new StringBuilder();
							sb.append("HT:");
							field = fields.get(17L);
							sb.append(field.getSelectedValue()).append("~");
							field = fields.get(16L);
							sb.append(field.getSelectedValue()).append("\n");
							sb.append("RT:");
							field = fields.get(20L);
							sb.append(field.getSelectedValue()).append("~");
							field = fields.get(19L);
							sb.append(field.getSelectedValue()).append("\n");
							sb.append("LT:");
							field = fields.get(23L);
							sb.append(field.getSelectedValue()).append("~");
							field = fields.get(22L);
							sb.append(field.getSelectedValue()).append("\n");
							record.put("storageTime", sb.toString());
						} else if (model.getModelId() == 20) {// linear impact
							field = fields.get(270L);
							record.put("temp", field.getSelectedValue());
							field = fields.get(340L);
							record.put("amount", String
									.valueOf(getAmountFromGridField(field,
											"TestQuantity")));
						} else if (model.getModelId() == 21) {// head impact
							field = fields.get(284L);
							record.put("temp", field.getSelectedValue());
							field = fields.get(261L);
							record.put("amount", String
									.valueOf(getAmountFromGridField(field,
											"TestQuantity")));
						} else if (model.getModelId() == 22) {// body block
							field = fields.get(296L);
							record.put("temp", field.getSelectedValue());
							field = fields.get(191L);
							record.put("amount", String
									.valueOf(getAmountFromGridField(field,
											"TestQuantity")));
						} else if (model.getModelId() == 23) {// push test
							field = fields.get(315L);
							record.put("temp", field.getSelectedValue());
							field = fields.get(335L);
							record.put("amount", String
									.valueOf(getAmountFromGridField(field,
											"TestQuantity")));
						}

						if (scheduleInfoMap != null) {
							OrderScheduleInfo scheduleInfo = scheduleInfoMap
									.get(model.getClientUniqueId());
							if (scheduleInfo != null) {
								if (status > -999) {
									if (scheduleInfo.getStatusName() != null) {
										orderStatusFlag = (scheduleInfo
												.getStatus() == status);
									}
								}
								inSchedule = true;
								record.put("condition", scheduleInfo
										.getCondition());
								record.put("duration", scheduleInfo
										.getDuration());
								if (scheduleInfo.getStartTime() != null) {
									record.put("startDate",
											TRPConstants.DATE_FORMAT
													.format(scheduleInfo
															.getStartTime()));
								}
								if (scheduleInfo.getEndTime() != null) {
									record.put("endDate",
											TRPConstants.DATE_FORMAT
													.format(scheduleInfo
															.getEndTime()));
								}
								record.put("testLocation", scheduleInfo
										.getTestLocation());
								record.put("outSourcing", scheduleInfo
										.getIsOutSourcing());
								record.put("sample", scheduleInfo.getSample());
								record
										.put("fixture", scheduleInfo
												.getFixture());
								if (scheduleInfo.getStatusName() != null) {
									// override order status here
									record.put("status", scheduleInfo
											.getStatusName());
								}
							}
						}

						if (!orderStatusFlag) {
							continue;
						}

						if (onlyPending) {
							if (inSchedule) {
								json.add(record);
							}
						} else {
							json.add(record);
						}
					}
				}
			}
		}
		return json;
	}

	public void saveSchedule() throws IOException {
		String requestNModels = getParamFromRequest("requestNModels");
		String fixture = getParamFromRequest("fixture");
		String duration = getParamFromRequest("duration");
		String outSourcing = getParamFromRequest("outSourcing");
		String testLocation = getParamFromRequest("testLocation");
		List<OrderBean> orderList = new ArrayList<OrderBean>();
		UserBean user = (UserBean) TRPUtil
				.getFromSession(TRPConstants.CURRENT_USER);

		String[] requestNModelArr = requestNModels.split(TRPConstants.COMMA);
		String[] fixtureArr = fixture == null ? null : fixture
				.split(TRPConstants.COMMA);
		String[] durationArr = duration == null ? null : duration
				.split(TRPConstants.COMMA);
		String[] outSourcingArr = outSourcing == null ? null : outSourcing
				.split(TRPConstants.COMMA);
		String[] testLocationArr = testLocation == null ? null : testLocation
				.split(TRPConstants.COMMA);

		long orgOrderId = -1;
		OrderBean order = null;
		for (int i = 0; i < requestNModelArr.length; i++) {
			String[] tmpStr = requestNModelArr[i].split(TRPConstants.DASH);
			if (tmpStr.length != 2) {
				log.warn("wrong param:" + tmpStr);
				continue;
			} else {
				try {
					long orderId = Long.parseLong(tmpStr[0]);
					String clientUniqueId = tmpStr[1];
					if (orderId != orgOrderId) {
						orgOrderId = orderId;
						order = new OrderBean();
						order.setOrderId(orderId);
						orderList.add(order);
					}
					if (order.getScheduleInfoMap() == null) {
						order
								.setScheduleInfoMap(new HashMap<String, OrderScheduleInfo>());
					}
					OrderScheduleInfo scheduleInfo = new OrderScheduleInfo();
					if (durationArr != null
							&& durationArr.length == requestNModelArr.length) {
						scheduleInfo.setDuration(durationArr[i]);
						scheduleInfo.setFixture(fixtureArr[i]);
						scheduleInfo.setIsOutSourcing(outSourcingArr[i]);
						scheduleInfo.setTestLocation(testLocationArr[i]);
					}
					order.getScheduleInfoMap()
							.put(clientUniqueId, scheduleInfo);
				} catch (NumberFormatException e) {
					log.warn("wrong param:" + tmpStr);
				}
			}
		}
		OrderDao dao = DaoFactory.getOrderDao();
		dao.createScheduleInfo(orderList, user);
		ResultMessage msg = new ResultMessage();
		msg.setState(ResultMessage.SUCCESS);
		writeJSON(msg);
	}

	public void UpdateScheduleTimeSlot() throws IOException {
		String orderIds = getParamFromRequest("orderIds");
		String clientUniqueIds = getParamFromRequest("clientUniqueIds");
		String startDates = getParamFromRequest("startDates");
		String endDates = getParamFromRequest("endDates");
		if (!StringUtils.isEmpty(orderIds)
				&& !StringUtils.isEmpty(clientUniqueIds)
				&& !StringUtils.isEmpty(startDates)
				&& !StringUtils.isEmpty(endDates)) {
			String[] orderIdArr = orderIds.split(TRPConstants.COMMA);
			String[] clientUniqueIdArr = clientUniqueIds
					.split(TRPConstants.COMMA);
			String[] startDateArr = startDates.split(TRPConstants.COMMA);
			String[] endDateArr = endDates.split(TRPConstants.COMMA);
			if (orderIdArr.length != clientUniqueIdArr.length
					|| orderIdArr.length != startDateArr.length
					|| orderIdArr.length != endDateArr.length) {
				log.warn("wrong param:" + orderIds + " " + clientUniqueIds
						+ " " + startDates + " " + endDates);
			} else {
				List<OrderScheduleInfo> scheduleInfoList = new ArrayList<OrderScheduleInfo>();
				for (int i = 0; i < orderIdArr.length; i++) {
					long orderId = -1;
					Date startDate = null;
					Date endDate = null;
					String clientUniqueId = clientUniqueIdArr[i];
					try {
						orderId = Long.parseLong(orderIdArr[i]);
						startDate = TRPConstants.DATE_FORMAT
								.parse(startDateArr[i]);
						endDate = TRPConstants.DATE_FORMAT.parse(endDateArr[i]);
						OrderScheduleInfo orderScheduleInfo = new OrderScheduleInfo();
						orderScheduleInfo.setOrderId(orderId);
						orderScheduleInfo.setClientUniqueId(clientUniqueId);
						orderScheduleInfo.setStartTime(startDate);
						orderScheduleInfo.setEndTime(endDate);
						scheduleInfoList.add(orderScheduleInfo);
					} catch (Exception e) {
						log.warn("wrong format:" + e);
						continue;
					}
				}
				OrderDao dao = DaoFactory.getOrderDao();
				dao.updateScheduleTimeSlot(scheduleInfoList);
			}
		}

		ResultMessage msg = new ResultMessage();
		msg.setState(ResultMessage.SUCCESS);
		writeJSON(msg);
	}

	public void UpdateScheduleStatus() throws IOException {
		long orderId = -1;
		String clientUniqueId = null;
		int newStatus = -999;
		try {
			orderId = Long.parseLong(getParamFromRequest("orderId"));
			clientUniqueId = getParamFromRequest("clientUniqueId");
			newStatus = Integer.parseInt(getParamFromRequest("newStatus"));
		} catch (Exception e) {
			log.warn("wrong format:" + e);
		}
		if (orderId > -1 && newStatus > -999) {
			OrderDao dao = DaoFactory.getOrderDao();
			dao.updateScheduleStatus(orderId, clientUniqueId, newStatus);
		}
		ResultMessage msg = new ResultMessage();
		msg.setState(ResultMessage.SUCCESS);
		writeJSON(msg);
	}

	public void getScheduledData() throws IOException {
		String year = getParamFromRequest("year");
		String month = getParamFromRequest("month");
		Map<String, List<String>> jsonMap = null;
		try {
			int yearInt = Integer.parseInt(year);
			int monthInt = Integer.parseInt(month);
			Calendar cal = new GregorianCalendar();
			cal.set(yearInt, monthInt - 1, 1);
			cal.set(Calendar.HOUR_OF_DAY, 0);
			cal.set(Calendar.MINUTE, 0);
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			Date startDate = cal.getTime();
			cal.add(Calendar.MONTH, 1);
			Date endDate = cal.getTime();
			OrderDao dao = DaoFactory.getOrderDao();
			SearchCriteriaBean criteria = new SearchCriteriaBean();
			criteria.setDetail(true);
			criteria.setMaxStatus(13);
			criteria.setMinStatus(3);
			List<OrderBean> orderList = dao.getOrders(criteria);
			jsonMap = new HashMap<String, List<String>>();
			for (OrderBean order : orderList) {
				Map<String, OrderScheduleInfo> scheduleMap = order
						.getScheduleInfoMap();
				List<ModelDetail> detailList = order.getDetailMap().get(1);
				List<ModelBean> modelList = order.getModelMap().get(1);
				if (scheduleMap != null) {
					Collection<OrderScheduleInfo> schedules = scheduleMap
							.values();
					for (OrderScheduleInfo schedule : schedules) {
						Date sDate = schedule.getStartTime();
						Date eDate = schedule.getEndTime();
						String clientUniqueId = schedule.getClientUniqueId();
						ModelDetail detail = null;
						for (int i = 0; i < modelList.size(); i++) {
							ModelBean model = modelList.get(i);
							if (clientUniqueId
									.equals(model.getClientUniqueId())) {
								detail = detailList.get(i);
							}
						}
						if (sDate != null
								&& eDate != null
								&& (eDate.compareTo(startDate) >= 0 && sDate
										.compareTo(endDate) <= 0)) {
							cal.setTime(sDate.compareTo(startDate) > 0 ? sDate
									: startDate);
							while (true) {
								int day = cal.get(Calendar.DATE);
								List<String> jsonList = jsonMap.get(String
										.valueOf(day));
								if (jsonList == null) {
									jsonList = new ArrayList<String>();
									jsonMap.put(DATE_FORMAT.format(cal.getTime()), jsonList);
								}
								if (detail != null) {
									StringBuilder msg = new StringBuilder();
									if (detail.getModelId() == 12) {
										Map<Long, ModelDetail.Field> fields = ModelUtil
												.getAllFields(detail);
										int ht = 0, rt = 0, lt = 0;
										try {
											ModelDetail.Field field = fields
													.get(75L);
											ht += Integer.parseInt(field
													.getSelectedValue());
										} catch (Exception e) {
										}
										try {
											ModelDetail.Field field = fields
													.get(91L);
											ht += Integer.parseInt(field
													.getSelectedValue());
										} catch (Exception e) {
										}
										try {
											ModelDetail.Field field = fields
													.get(107L);
											ht += Integer.parseInt(field
													.getSelectedValue());
										} catch (Exception e) {
										}
										try {
											ModelDetail.Field field = fields
													.get(76L);
											rt += Integer.parseInt(field
													.getSelectedValue());
										} catch (Exception e) {
										}
										try {
											ModelDetail.Field field = fields
													.get(92L);
											rt += Integer.parseInt(field
													.getSelectedValue());
										} catch (Exception e) {
										}
										try {
											ModelDetail.Field field = fields
													.get(108L);
											rt += Integer.parseInt(field
													.getSelectedValue());
										} catch (Exception e) {
										}
										try {
											ModelDetail.Field field = fields
													.get(77L);
											lt += Integer.parseInt(field
													.getSelectedValue());
										} catch (Exception e) {
										}
										try {
											ModelDetail.Field field = fields
													.get(93L);
											lt += Integer.parseInt(field
													.getSelectedValue());
										} catch (Exception e) {
										}
										try {
											ModelDetail.Field field = fields
													.get(109L);
											lt += Integer.parseInt(field
													.getSelectedValue());
										} catch (Exception e) {
										}
										msg.append(order.getOrderNumber())
												.append(" ").append(
														order.getGeneralInfo()
																.getProject())
												.append(" ").append(
														order.getGeneralInfo()
																.getProduct());
										msg.append(" HT*").append(ht);
										msg.append(" RT*").append(rt);
										msg.append(" LT*").append(lt);
										msg.append(" "+ schedule.getTestLocation());
									}
									jsonList.add(msg.toString());
								}
								cal.add(Calendar.DATE, 1);
								if (cal.get(Calendar.MONTH) != monthInt - 1
										|| cal.getTime().compareTo(eDate) > 0) {
									break;
								}
							}
						}
					}
				}
			}
		} catch (NumberFormatException e) {
			log.warn("wrong param [year:" + year + ",month:" + month + "]");
		}
		writeJSON(jsonMap);
	}

	private int getAmountFromGridField(ModelDetail.Field field,
			String columnName) {
		List<JSONObject> gridJson = ModelUtil.parseMatrix(field);
		int amount = 0;
		for (JSONObject jsonObj : gridJson) {
			try {
				amount += Integer.parseInt(jsonObj.get(columnName).toString());
			} catch (Exception e) {
			}
		}
		return amount;
	}
}
